#pragma once
#ifndef skyObject_h__
#define skyObject_h__

#include "./skyType.h"
#include "./skyRtti.h"
#include "./skyPtr.h"

namespace Sky
{



	//////////////////////////////////////////////////////////////////////////
	class Memory
	{
	public:
		static TInt alloc_count;
		static TInt free_count;
	public:
		static TVoid* alloc(size_t size);
		static TVoid* realloc(TVoid* p,size_t size);
		static TVoid  free(TVoid* p);
		static TVoid  copy(TVoid* dst,const TVoid* src,size_t size);
		static TVoid  set(TVoid* dst,TUint n,size_t size);
		static TVoid* clone(size_t size,const TVoid* src);
		TVoid* operator new(size_t size);                              
		TVoid  operator delete(TVoid* p);                                   
		TVoid* operator new[](size_t size);                                   
		TVoid  operator delete[](TVoid* p);
	};
	//////////////////////////////////////////////////////////////////////////

	class String;
	typedef RefPtr<String> StringPtr;
	class Object : public Memory
	{
		friend class sky_new;
		DECL_RTTI0(Object);
	public:		

		Object();
		TBool isOnHeap(){return _ref != 0x80000000;}
		virtual TVoid incRef();
		virtual TVoid decRef();
		virtual ~Object();
		virtual TBool cloneFrom(const Object* other);
		virtual StringPtr toString(StringPtr str = StringPtr());
	protected:
		TInt _ref;
	};
	typedef RefPtr<Object> ObjectPtr;


	class PtrWrapper
	{
	protected:
		Object* ptr;
	public:
		PtrWrapper():ptr(vNull){}
		~PtrWrapper();
	public:
		Object* leakPtr(){return ptr;}

	};

	template <typename CLS>
	class AutoPtr
	{
	public:
		typedef CLS type;
		CLS* ptr;
	public:
		AutoPtr(){}
		AutoPtr(CLS * p){ptr = p;}
		~AutoPtr(){if(ptr)delete ptr;}
	};
	//////////////////////////////////////////////////////////////////////////
	template <typename CLS>
	class RefPtr : public PtrWrapper
	{
	public:
		typedef CLS type;
	public:
		RefPtr(){}

		RefPtr(CLS* p);

		~RefPtr(){}

		RefPtr(RefPtr& r);

		template <typename CLS2>
		RefPtr( RefPtr<CLS2>& rref );

		void operator = (RefPtr& rref);
		void operator = (CLS* p);
		//void operator = (CLS& p)
		//{
		//	if(p == vNull)
		//	{
		//		p = new (CLS(p));
		//	}
		//}
		CLS* operator ->();

		CLS* leakPtr();

		operator CLS* () { return leakPtr(); }

	};
	template <typename CLS>
	void RefPtr<CLS>::operator=( RefPtr& rref )
	{
		if(rref)rref->incRef();
		if(ptr)ptr->decRef();
		ptr = rref.leakPtr();
	}

	//////////////////////////////////////////////////////////////////////////
	class sky_new
	{
	public:
		template <typename T>
		static RefPtr<T> skynew_tap(T* p)
		{
			p->_ref = 0;
			return p;
		}
	};

	template <typename CLS>
	void RefPtr<CLS>::operator=( CLS* p )
	{
		if(p)p->incRef();
		if(ptr)ptr->decRef();
		ptr = p;
	}


	template <typename CLS>
	CLS* RefPtr<CLS>::operator->()
	{
		return leakPtr();
	}


	template <typename CLS>
	CLS* RefPtr<CLS>::leakPtr()
	{
		return (CLS*)PtrWrapper::leakPtr();
	}


	template <typename CLS2>
	RefPtr<CLS2>::RefPtr( RefPtr<CLS2>& rref )
	{
		if(rref)rref->incRef();
		if(ptr)ptr->decRef();
		ptr = rref.leakPtr();
	}


	template <typename CLS>
	RefPtr<CLS>::RefPtr( RefPtr& r )
	{
		if(r)r->incRef();
		if(ptr)ptr->decRef();
		ptr = r;
	}


	template <typename CLS>
	RefPtr<CLS>::RefPtr( CLS* p )
	{
		if(p)p->incRef();
		if(ptr)ptr->decRef();
		ptr = p;
	}
#define skynew(obj) sky_new::skynew_tap(new obj)

	
}

#endif // skyObject_h__
